﻿using Microsoft.Extensions.Caching.Memory;

namespace PmSoft.Caching
{
    /// <summary>
    /// 运行时内存缓存
    /// </summary>
    public class RuntimeMemoryCache : ICache
    {
        private readonly IMemoryCache cache;
        private static readonly Task CompletedTask = Task.FromResult<object?>(null);

        public RuntimeMemoryCache(IMemoryCache memoryCache)
        {
            this.cache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
        }

        /// <summary>
        /// 加入缓存项 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan">缓存失效时间</param>
        public void Add<T>(string key, T value, TimeSpan timeSpan)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            this.Set(key, value, timeSpan);
        }

        /// <summary>
        /// 加入缓存项 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan">缓存失效时间</param>
        public Task AddAsync<T>(string key, T value, TimeSpan timeSpan)
        {
            Add(key, value, timeSpan);

            return CompletedTask;
        }

        /// <summary>
        /// 获取缓存项
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public T? Get<T>(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            key = key.ToLower();

            return this.cache.Get<T>(key);
        }

        /// <summary>
        /// 获取缓存项
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<T?> GetAsync<T>(string key)
        {
            return await Task.FromResult(Get<T>(key));
        }

        /// <summary>
        /// 移除指定的缓存项
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            key = key.ToLower();
            this.cache.Remove(key);
        }

        /// <summary>
        /// 移除指定的缓存项
        /// </summary>
        /// <param name="key"></param>
        public Task RemoveAsync(string key)
        {
            Remove(key);
            return CompletedTask;
        }

        /// <summary>
        /// 如果不存在缓存项则添加，否则更新
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan"></param>
        public void Set<T>(string key, T value, TimeSpan timeSpan)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (!string.IsNullOrEmpty(key) && (value != null))
            {
                key = key.ToLower();

                this.cache.Set<T>(key, value, timeSpan);
            }
        }

        /// <summary>
        /// 如果不存在缓存项则添加，否则更新
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan"></param>
        public Task SetAsync<T>(string key, T value, TimeSpan timeSpan)
        {
            Set(key, value, timeSpan);
            return CompletedTask;
        }

    }
}
